/**
 * 
 */
package com.star.util.xml;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.List;

import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

/**
 * @ClassName: XStreamUtils
 * @Description: TODO
 * @author starhq
 * @createtime 2014年7月20日 下午2:35:47
 * @email : jian.wang@shinsoft.net
 * @modify by TODO
 * @resaon
 * @edittime
 * @version 1.0
 * @copyright shinsoft
 */
public class XStreamUtils {

	// object to xml
	public static String getObjectToXml(Object classType) {
		return getObjectToXml(classType, "");
	}

	public static String getObjectToXmlCustom(Object classType) {
		return getObjectToXml(classType, "按需求");
	}

	public static String getObjectToXml(Object classType, String rootElementName) {
		try {
			XStream xStream = new XStream(new DomDriver());
			if (StringUtils.hasText(rootElementName)) {
				xStream.alias(rootElementName, classType.getClass());
			}
			return xStream.toXML(classType);
		} catch (Exception e) {
			return null;
		}
	}

	// xml to object
	public static <T> T getXMLToObject(String xml, String rootElementName,
			Class<T> rootElementClass) {
		try {
			XStream stream = new XStream(new DomDriver());
			if (StringUtils.hasText(rootElementName)) {
				stream.alias(rootElementName, rootElementClass);
			}
			return (T) stream.fromXML(xml);
		} catch (Exception e) {
			return null;
		}
	}

	// 根据项目，可以写死rootelementname
	// 默认生成的xml可用这种方式还原
	public static Object getXMLToObject(String xml) {
		return getXMLToObject(xml, "", null);
	}

	// classtype不能为空
	public static Object getXMLToObjectCustom(String xml) {
		return getXMLToObject(xml, "按需求", null);
	}

	/*
	 * xml可能需要处理下，把根节点替换成list
	 * 
	 * 也可以用java.util.list来替换别名
	 * 
	 * xml转换接触太少可能还需扩展
	 */
	// xml to list
	// 同时注册两个别名好像有问题
	public static <T> Collection<T> getXMLToList(String xml,
			String rootElementName, String elementName, Class<T> elementClass) {
		try {
			XStream xstream = new XStream(new DomDriver());
			if (StringUtils.hasText(rootElementName)) {
				xml = xml.replace(rootElementName, "list");
			}
			if (StringUtils.hasText(elementName)) {
				xstream.alias(elementName, elementClass);
			}
			return (Collection<T>) xstream.fromXML(xml);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public static void main(String[] args) {
		String xml = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>"
				+ "<item>" + " <passWord>12345678</passWord>"
				+ " <UserName>starhq</UserName>" + "</item>";

		System.out.println(getXMLToObject(xml, "item", User.class)
				.getUserName());

		// long start = System.currentTimeMillis();

		// Person p = new Person();
		// p.setBirthDay(new Date());
		// p.setUserId(1);
		// p.setUsername("王坚");
		//
		// Person p1 = new Person();
		// p1.setBirthDay(new Date());
		// p1.setUserId(2);
		// p1.setUsername("小胖");
		//
		// List<Person> persons = new ArrayList<Person>(2);
		// persons.add(p);
		// persons.add(p1);
		//
		// System.out.println(getListToXML(persons));

		// String xml =
		// "<list><com.star.util.xml.Person><userId>1</userId><username>王坚</username><birthDay>2014-08-01 05:25:02.966 UTC</birthDay></com.star.util.xml.Person><com.star.util.xml.Person><userId>2</userId><username>小胖</username><birthDay>2014-08-01 05:25:02.967 UTC</birthDay></com.star.util.xml.Person></list>";

		// getXMLToList(xml);

		// System.out.println("--------------------------");
		// System.out.println(System.currentTimeMillis() - start);
	}

	// xml to list
	// 默认生成的xml用这种方式还原
	public static Object getXMLToList(String xml) {
		return getXMLToList(xml, "", "", null);
	}

	// elementclass不能为空
	public static <T> Collection<T> getXMLToListCustom(String xml,
			Class<T> elementClass) {
		return getXMLToList(xml, "需求", "需求", elementClass);
	}

	// list to xml
	public static String getListToXML(List<?> classType, String elementName,
			String rootElementName) {
		if (CollectionUtils.isEmpty(classType)) {
			return "";
		}
		XStream xStream = new XStream(new DomDriver());
		if (StringUtils.hasText(elementName)) {
			for (int i = 0; i < classType.size(); i++) {
				xStream.alias(elementName, classType.get(i).getClass());
			}
		}
		if (StringUtils.hasText(rootElementName)) {
			xStream.alias(rootElementName, List.class);
		}
		return xStream.toXML(classType);
	}

	// 默认情况下，可用这种方式还原
	public static String getListToXML(List<?> classType) {
		return getListToXML(classType, "", "");
	}

	// 按实际情况写死
	public static String getListToXMLCustom(List<?> classType) {
		return getListToXML(classType, "按需求", "按需求");
	}

	// 对象写入xml
	public static boolean toXMLFile(Object obj, String absPath, String fileName) {

		String strXml = getObjectToXml(obj);
		String filePath = absPath + fileName;
		File file = new File(filePath);
		if (!file.exists()) {
			try {
				file.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
				return false;
			}

		}
		OutputStream ous = null;
		try {
			ous = new FileOutputStream(file);
			ous.write(strXml.getBytes());
			ous.flush();
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} finally {
			if (ous != null)
				try {
					ous.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
		return true;
	}

	// 集合写入xml
	public static boolean toXMLFile(List<?> classType, String rootElementName,
			String elementName, String absPath, String fileName) {

		String strXml = getListToXML(classType, elementName, rootElementName);
		String filePath = absPath + fileName;
		File file = new File(filePath);
		if (!file.exists()) {
			try {
				file.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
				return false;
			}

		}
		OutputStream ous = null;
		try {
			ous = new FileOutputStream(file);
			ous.write(strXml.getBytes());
			ous.flush();
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} finally {
			if (ous != null)
				try {
					ous.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
		return true;
	}

	public static boolean toXMLFile(List<?> classType, String absPath,
			String fileName) {

		String strXml = getListToXML(classType);
		String filePath = absPath + fileName;
		File file = new File(filePath);
		if (!file.exists()) {
			try {
				file.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
				return false;
			}

		}
		OutputStream ous = null;
		try {
			ous = new FileOutputStream(file);
			ous.write(strXml.getBytes());
			ous.flush();
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} finally {
			if (ous != null)
				try {
					ous.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
		return true;
	}

	public static <T> T toBeanFromFile(String absPath, String fileName)
			throws Exception {

		String filePath = absPath + fileName;
		InputStream ins = null;
		try {
			ins = new FileInputStream(new File(filePath));
		} catch (Exception e) {
			throw new Exception("读{" + filePath + "}文件失败！", e);
		}
		XStream xstream = new XStream(new DomDriver());
		T obj = null;
		try {
			obj = (T) xstream.fromXML(ins);
		} catch (Exception e) {
			throw new Exception("解析{" + filePath + "}文件失败！", e);
		}
		if (ins != null)
			ins.close();
		return obj;
	}

	public static <T> T toBeanFromFile(String absPath, String fileName,
			String rootElementName, String elementName, Class<?> classType)
			throws Exception {

		String filePath = absPath + fileName;
		InputStream ins = null;
		try {
			ins = new FileInputStream(new File(filePath));
		} catch (Exception e) {
			throw new Exception("读{" + filePath + "}文件失败！", e);
		}
		XStream xstream = new XStream(new DomDriver());
		if (StringUtils.hasText(rootElementName)) {
			xstream.alias(rootElementName, List.class);
		}
		if (StringUtils.hasText(elementName)) {
			xstream.alias(elementName, classType);
		}
		T obj = null;
		try {
			obj = (T) xstream.fromXML(ins);
		} catch (Exception e) {
			throw new Exception("解析{" + filePath + "}文件失败！", e);
		}
		if (ins != null)
			ins.close();
		return obj;
	}

}
